#include "CustomEvent.h"
#include "Mouse.h"
#include <cassert>
namespace NBE
{
	Mouse::Mouse():Input(MOUSE)
	{
		for(UINT i = 0; i < MAX_BUTTONS; ++i)
		{
			m_buttonStates[i] = m_lastButtonStates[i] = false;
		}
	}
	Mouse::~Mouse()
	{}
	void Mouse::init(HWND hwnd)
	{
		m_hWnd = hwnd;
	}
	void Mouse::calculateCenter(HWND hwnd)
	{

		RECT cRect,wRect;
		GetClientRect( hwnd, &cRect );
		GetWindowRect(hwnd, &wRect);
		int border_thickness = (wRect.right - wRect.left - cRect.right) /2;

		LONG MOUSE_CENTER_X = cRect.right / 2 + border_thickness + wRect.left; 
		LONG MOUSE_CENTER_Y = (cRect.bottom - cRect.top +45) / 2 + wRect.top;
		setCent(MOUSE_CENTER_X, MOUSE_CENTER_Y);
		//::SetCursorPos(MOUSE_CENTER_X,MOUSE_CENTER_Y);
		//::ShowCursor(false);
	}

	void Mouse::setCent(LONG _X, LONG _Y)
	{
		m_lastX = _X;
		m_lastY = _Y;
	}

	void Mouse::update()
	{
		POINT mousePos;
		::GetCursorPos(&mousePos);

		//how fast did the mouse move?

		const float MOUSE_ROTATION_SCALAR =  0.1f ;
		vec3f mouseDelta( 0,MOUSE_ROTATION_SCALAR * (mousePos.y-m_lastY)+
			MOUSE_ROTATION_SCALAR * (mousePos.x-m_lastX),0);

		//addEvent(new MouseEvent(MOUSE_MOVE,mouseDelta)); //move event
		
		




		//::SetCursorPos(m_lastX,m_lastY);

		for(UINT i = 0; i < MAX_BUTTONS; ++i)
		{
			if(m_buttonStates[ i ] && !m_lastButtonStates[ i ])
			{
				 addEvent(new MouseEvent(MOUSE_BUTTON_PRESS,i)); // press button once
			}
		
			if(m_buttonStates[ i ])
				addEvent(new MouseEvent(MOUSE_BUTTON_DOWN,i));
			else if(!m_buttonStates[ i ] && m_lastButtonStates[ i ])
				addEvent(new MouseEvent(MOUSE_BUTTON_RELEASE,i));


			m_lastButtonStates[i] = m_buttonStates[i];
		}
	}
	void Mouse::processMessages(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
	{
		int bt;bool btV;
		switch( message )
		{
		case WM_LBUTTONDOWN:
			bt = LEFT_BUTTON;btV = true;
			break;
		case WM_LBUTTONUP:
			bt = LEFT_BUTTON;btV = false;
			break;
		case WM_RBUTTONDOWN:
			bt = RIGHT_BUTTON;btV = true;
			break;
		case WM_RBUTTONUP:
			bt = RIGHT_BUTTON;btV = false;
			break;
		case WM_MBUTTONDOWN:
			bt = MIDDLE_BUTTON;btV = true;
			break;
		case WM_MBUTTONUP:
			bt = MIDDLE_BUTTON;btV = false;
			break;
		default:
			return;
		}

		 m_buttonStates[bt] = btV;

		   
	}

	unsigned int Mouse::getNumOfButtons() const
	{
		return MAX_BUTTONS;
	}
	
	vec2f Mouse::getPosition() const
	{
		POINT mousePos;
		GetCursorPos(&mousePos);
		ScreenToClient(m_hWnd,&mousePos);
		return vec2f(static_cast<float>(mousePos.x),static_cast<float>(mousePos.y));
	}
	bool Mouse::didGoUp( MouseButton button) const
	{
		assert( button < MAX_BUTTONS );
		return !m_buttonStates[ button ] && m_lastButtonStates[ button ];
	}
	bool Mouse::didGoDown( MouseButton button ) const
	{
		assert( button < MAX_BUTTONS );
		return m_buttonStates[ button ] && !m_lastButtonStates[ button ];
	}
	bool Mouse::isDown( MouseButton button ) const
	{
		assert( button< MAX_BUTTONS);
		return m_buttonStates[ button ];
	}


	////----Mouse related event implementation
	MouseEvent::MouseEvent(EventType _t,vec3f& delta, LONG currentX=0, LONG currentZ=0):Event(_t), deltaMove(delta){}
	MouseEvent::MouseEvent(EventType _t,unsigned int _bt):Event(_t),bt(_bt){}
	MouseEvent::~MouseEvent(){}


}